package com.neusoft.bookstore.customer.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.neusoft.bookstore.customer.mapper.CustomerMappper;
import com.neusoft.bookstore.customer.model.Customer;
import com.neusoft.bookstore.customer.service.CustomerService;
import com.neusoft.bookstore.util.ErrorCode;
import com.neusoft.bookstore.util.MD5Util;
import com.neusoft.bookstore.util.MethodUtils;
import com.neusoft.bookstore.util.ResponseVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName CustomerServiceImpl
 * @Author yins
 * @Date 2020/4/23 11:00
 */
@Service
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private CustomerMappper customerMappper;

    @Autowired
    private MethodUtils methodUtils;


    /**
     * 新增（注册）用户
     *
     * @param customer
     * @return
     */
    @Override
    public ResponseVo addCustomer(Customer customer) {
        /**
         *   用户新增 ：
         *     1： 需要校验前台输入的用户名（用户账号）和手机号在系统中是否唯一
         *     2： 我们需要校验 是app注册 还是pc 注册 用过isAdmin（前台给值） 只需要校验 isAdmin是否规范（0或者1）
         *     3： 用户输入的密码 需要加密  MD5
         *     4：还要处理用户输入的金额（类型转换  String -->BigDecimal）  JSON
         */


        // 定义返回值
        ResponseVo responseVo = new ResponseVo(false,ErrorCode.FAIL,"新增失败");
        String result = "";
        // 1： 需要校验前台输入的用户名（用户账号）和手机号在系统中是否唯一
        // 取出 手机号和 用户账号
        Customer customerByDb = customerMappper.findCustomerByPhoneAndAccount(customer);
        if (customerByDb != null) {
            // 数据库有值 页面输入有重复
            responseVo.setMsg("注册失败，用户账号或者手机号已存在，请检查后重试！");
            return responseVo;
        }

        // 2： 我们需要校验 是app注册 还是pc 注册 用过isAdmin（前台给值） 只需要校验 isAdmin是否规范（0或者1）
        Integer isAdmin = customer.getIsAdmin();
        if (!StringUtils.isEmpty(isAdmin)) {
            // 校验
            if (isAdmin != 0 && isAdmin != 1) {
                //  错误
                responseVo.setMsg("注册失败，无法判断是app注册还是pc注册，请检查后重试！");
                return responseVo;
            }

        } else {
            responseVo.setMsg("isAdmin不能为空！");
            return responseVo;
        }
        // 3： 用户输入的密码 需要加密  MD5
        String password = customer.getPassword();
        // 加密密码
        String inputPassToFormPass = MD5Util.inputPassToFormPass(password);
        // 覆盖原始密码
        customer.setPassword(inputPassToFormPass);

        //4：还要处理用户输入的金额（类型转换  String -->BigDecimal）  JSON
        // 金额处理，一般来说 前后台交互都是Json数据格式  string -BigDecimal
        BigDecimal score = new BigDecimal(customer.getFrontScore());
        // 赋值customer 中的score
        customer.setScore(score);
        // 5：对创建人  赋值
        // todo  等登陆功能写完添加
        // 从redis中获取当前登陆人的用户信息
        String createdBy = methodUtils.getLoginInfo(customer.getLoginAccount());
        customer.setCreatedBy(createdBy);
        // 入库操作
        int res = customerMappper.addCustomer(customer);
        if (res != 1) {
            // 失败
            responseVo.setMsg("新增失败！");
            return responseVo;
        }
        responseVo.setSuccess(true);
        responseVo.setCode(ErrorCode.SUCCESS);
        responseVo.setMsg("新增成功！");
        return responseVo;
    }




    /**
     * 用户登陆
     * @param customer
     * @return
     */
    @Override
    public ResponseVo login(Customer customer) {
        /**
         *   登陆： （1）1： pc端的登陆   2：app的登陆
         *          区分： 前端无声给后台传值 isadmin 0 1
         *         （2） 手机号或者用户账号： loginAccount
         *         （3） 密码： 输入加密前 （加密）   数据库 密码：加密后的
         *         （4） 登陆的时候 用到了redis 因为在redis中 保存了 当前登陆的用户信息
         */
        // 定义返回值
        ResponseVo responseVo = new ResponseVo(false, ErrorCode.FAIL, "用户名或手机号不存在、密码错误，登陆失败！");

        //校验数据肥非空  账号信息和密码信息
        if(StringUtils.isEmpty(customer.getLoginAccount())){
            //账号信息为空
            responseVo.setMsg("用户账号或者是手机号不能为空！");
            return responseVo;
        }
        if(StringUtils.isEmpty(customer.getPassword())){
            //账号信息为空
            responseVo.setMsg("用户不能为空不能为空！");
            return responseVo;
        }
        //密码加密
        String password = customer.getPassword();
        String inputPassToFormPass = MD5Util.inputPassToFormPass(password);
        customer.setPassword(inputPassToFormPass);

        // 去数据库匹配
        Customer customerByBb=customerMappper.selectLoginCustomer(customer);
        if(customerByBb!=null){
            // 登陆成功，保存用户信息到redis
            responseVo.setMsg("登陆成功");
            responseVo.setSuccess(true);
            responseVo.setCode(ErrorCode.SUCCESS);
            // 返回前台登陆的用户信息
            responseVo.setData(customerByBb);
            //保存用户信息到redis      确定key 和value
            // key ？？？？？  用户账号
            methodUtils.setLoginInfo(customerByBb.getUserAccount(),customerByBb);
//            redisTemplate.opsForValue().set(customerByBb.getUserAccount(),customerByBb);
            return responseVo;
        }
        return responseVo;
    }


    /**
     * 用户退出
     * @param userAccount
     * @return
     */
    @Override
    public ResponseVo loginOut(String userAccount) {
        // 定义返回值
        ResponseVo responseVo = new ResponseVo(false, ErrorCode.FAIL, "退出失败！");
        // 校验userAccount
        if(StringUtils.isEmpty(userAccount)){
            responseVo.setMsg("用户信息不完整，退出失败！");
            return responseVo;
        }
        // 有值
        // 从redis 里面清除 userAccount 对应的用户信息   del key
        Boolean result = methodUtils.deleteKey(userAccount);
        if(result){
             // redis key 删除成功
            responseVo.setMsg("退出成功！");
            responseVo.setCode(ErrorCode.SUCCESS);
            responseVo.setSuccess(true);
            return  responseVo;
        }
        return responseVo;
    }


    /**
     * 列表查询
     * @param customer
     * @return
     */
    @Override
    public ResponseVo listCustomers(Customer customer) {
        /**
         *  1： 所有的用户信息（未删除的信息）
         *  2： 有模糊查询的功能 （like）
         *  3： 封住分页信息 前端会给后台传值，传一个当前页，传每页显示的条数
         *        limit    page当前页：
         *          index：   (page-1)*size
         *           size： 每页显示的条数
         */
        ResponseVo responseVo = new ResponseVo(true, ErrorCode.SUCCESS, "查询成功！");

        //添加分页插件
        PageHelper.startPage(customer.getPageNum(),customer.getPageSize());
        //查询用户所有信息
        List<Customer> customerList=customerMappper.listCustomers(customer);

        //分装分页返回信息
        PageInfo<Customer> pageInfo=new PageInfo<>(customerList);
        responseVo.setData(pageInfo);
        return responseVo;
    }

    /**
     * 用户详情
     * @param id
     * @return
     */
    @Override
    public ResponseVo findCustomerById(Integer id) {
        // 定义返回值
        ResponseVo responseVo = new ResponseVo(true, ErrorCode.SUCCESS, "查询成功！");
        if(id==null){
             responseVo.setSuccess(false);
             responseVo.setCode(ErrorCode.FAIL);
             responseVo.setMsg("用户id不能为空");
             return  responseVo;
        }
        Customer customer=customerMappper.findCustomerById(id);
        if(customer==null){
            responseVo.setSuccess(false);
            responseVo.setCode(ErrorCode.FAIL);
            responseVo.setMsg("未查询到用户信息");
            return  responseVo;
        }
        responseVo.setData(customer);
        return responseVo;
    }

    /**
     * 根据用户id 修改用户信息
     * @param customer
     * @return
     */
    @Override
    public ResponseVo updateCustomerById(Customer customer) {
        /**
         *   用户新增 ：
         *     1： 需要校验前台输入的用户名（用户账号）和手机号在系统中是否唯一（要将该条记录排除在外）
         *     2：还要处理用户输入的金额（类型转换  String -->BigDecimal）  JSON
         *     3：修改人
         *     4：修改
         */

        // 定义返回值
         ResponseVo responseVo = new ResponseVo(false,ErrorCode.FAIL,"修改失败");

        //   1： 需要校验前台输入的用户名（用户账号）和手机号在系统中是否唯一（要将该条记录排除在外）
        Customer customerByDb = customerMappper.findCustomerByPhoneAndAccountExOwn(customer);
        if (customerByDb != null) {
            // 数据库有值 页面输入有重复
            responseVo.setMsg("修改失败，用户账号或者手机号已存在，请检查后重试！");
            return responseVo;
        }
        //2：还要处理用户输入的金额（类型转换  String -->BigDecimal）  JSON
        // 金额处理，一般来说 前后台交互都是Json数据格式  string -BigDecimal
        BigDecimal score = new BigDecimal(customer.getFrontScore());
        // 赋值customer 中的score
        customer.setScore(score);
        // 3：对修改  赋值
        // 从redis中获取当前登陆人的用户信息
      /*  Customer customerByRedis = (Customer) redisTemplate.opsForValue().get(customer.getLoginAccount());
        if(customerByRedis!=null){
            // redis已经保存
            customer.setUpdatedBy(customerByRedis.getUserAccount());
        }else{
            customer.setUpdatedBy("admin");
        }*/
        String loginInfo = methodUtils.getLoginInfo(customer.getLoginAccount());
        customer.setUpdatedBy(loginInfo);
        //4：修改
        int result=customerMappper.updateCustomerById(customer);
        if(result==1){
            responseVo.setMsg("修改成功");
            responseVo.setCode(ErrorCode.SUCCESS);
            responseVo.setSuccess(true);
            return responseVo;
        }
        return responseVo;
    }


    /**
     * 删除用户信息
     * @param id
     * @return
     */
    @Override
    public ResponseVo deleteCustomerById(Integer id) {
        /**
         * ......直接更新 is_DELETE 字段  ,
         * // todo 等完成 购物车的时候，需要添加逻辑
         */
        // 定义返回值
        ResponseVo responseVo = new ResponseVo(true, ErrorCode.SUCCESS, "删除成功！");
        if(id==null){
            responseVo.setSuccess(false);
            responseVo.setCode(ErrorCode.FAIL);
            responseVo.setMsg("用户id不能为空");
            return  responseVo;
        }
        int result=customerMappper.deleteCustomerById(id);
        if(result!=1){
            responseVo.setMsg("删除失败");
            responseVo.setCode(ErrorCode.FAIL);
            responseVo.setSuccess(false);
            return responseVo;
        }
        return responseVo;
    }


    /**
     * 根据用户id 更新用户密码 （app + pc）
     * @param originPwd
     * @param newPwd
     * @param userId
     * @param userAccount
     * @return
     */
    @Override
    public ResponseVo updatePwd(String originPwd, String newPwd, Integer userId, String userAccount) {

        ResponseVo responseVo = new ResponseVo(false, ErrorCode.FAIL, "密码修改失败");
        // 1： 数据校验
        if(StringUtils.isEmpty(originPwd) ||StringUtils.isEmpty(newPwd) ||userId==null ||StringUtils.isEmpty(userAccount)){
             // 其中某个值为空，返回
            responseVo.setMsg("密码或者账号账号信息为空！");
            return responseVo;
        }
        //2： // 原始密码需要校验需要加密
        Customer customerByDb = customerMappper.findCustomerById(userId);
        if(customerByDb==null){
            responseVo.setMsg("用户信息不存在！");
            return responseVo;
        }
        String inputPassToFormPass = MD5Util.inputPassToFormPass(originPwd);
        String password = customerByDb.getPassword();
        /**
         *   == 值和引用地址  比较
         *   equals 值比较
         */
        if(!inputPassToFormPass.equals(password)){
            // 原始密码校验不通过
            responseVo.setMsg("原始密码不正确！");
            return responseVo;
        }
        // 3：走修改
        // 新密码加密：
        newPwd = MD5Util.inputPassToFormPass(newPwd);
        Map<Object, Object> map = new HashMap<>();
        map.put("newPwd",newPwd);
        map.put("userId",userId);
        // 3：对修改  赋值
        // 从redis中获取当前登陆人的用户信息
//        Customer customerByRedis = (Customer) redisTemplate.opsForValue().get(userAccount);
//        if(customerByRedis!=null){
//            // redis已经保存
//            map.put("userAccount",userAccount);
//        }else{
//            /*responseVo.setMsg("请登陆！");
//            return responseVo;*/
//            map.put("userAccount","admin");
//        }
        String loginInfo = methodUtils.getLoginInfo(userAccount);
        map.put("userAccount",loginInfo);
        int result = customerMappper.updatePwdById(map);
        if(result==1){
            // 更新成功
            responseVo.setMsg("密码修改成功");
            responseVo.setCode(ErrorCode.SUCCESS);
            responseVo.setSuccess(true);
            return responseVo;
        }
        return responseVo;
    }
}
